vt-d: Fix print_vtd_entries walk VTd mapping table.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jan 2008 10:35:52 +0000 (10:35 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 9 Jan 2008 10:35:52 +0000 (10:35 +0000)
DMA request to above guest physical memory will cause VTd fault, in
which print_vtd_entries() tries to walk VTd mapping table. However,
during walking, current Xen code didn't check if the PTE is valid and
may access to invalid memory address.

Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
xen/arch/x86/hvm/vmx/vtd/dmar.c
xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
xen/arch/x86/hvm/vmx/vtd/utils.c

index 786186966f3665b3b16155c46e60f702fdb21670..62e32e36107555d8967513e3cfaa1e40a66c5c75 100644 (file)
@@ -103,7 +103,11 @@ struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev)
     list_for_each_entry ( drhd, &acpi_drhd_units, list )
     {
         if ( drhd->include_all )
+        {
             include_all_drhd = drhd;
+            continue;
+        }
+
         if ( acpi_pci_device_match(drhd->devices,
                                    drhd->devices_cnt, dev) )
         {
@@ -119,7 +123,7 @@ struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *dev)
         gdprintk(XENLOG_INFO VTDPREFIX, 
                  "acpi_find_matched_drhd_unit:include_all_drhd->addr = %lx\n",
                  include_all_drhd->address);
-        return include_all_drhd;;
+        return include_all_drhd;
     }
 
     return NULL;
@@ -513,7 +517,7 @@ static int __init acpi_parse_dmar(unsigned long phys_addr,
             ret = acpi_parse_one_rmrr(entry_header);
             break;
         case ACPI_DMAR_ATSR:
-            printk(KERN_INFO PREFIX "found ACPI_DMAR_RMRR\n");
+            printk(KERN_INFO PREFIX "found ACPI_DMAR_ATSR\n");
             ret = acpi_parse_one_atsr(entry_header);
             break;
         default:
index 29f8f195de0a2d6deac6f4bae7c0f99a448d3530..fb8fdb77a17caff0a6eeb5b43c44f6d20493004c 100644 (file)
@@ -528,7 +528,6 @@ void iommu_flush_all(void)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
-    int i = 0;
 
     wbinvd();
     for_each_drhd_unit ( drhd )
@@ -536,7 +535,6 @@ void iommu_flush_all(void)
         iommu = drhd->iommu;
         iommu_flush_context_global(iommu, 0);
         iommu_flush_iotlb_global(iommu, 0);
-        i++;
     }
 }
 
index 55a7149a7e02a9dbe9f4be3619f3f775d2348871..82f8366ae4dfcadfde12ae1cae14c04a27cf1a88 100644 (file)
@@ -154,8 +154,9 @@ void print_vtd_entries(struct domain *d, int bus, int devfn,
     struct iommu *iommu;
     struct context_entry *ctxt_entry;
     struct root_entry *root_entry;
-    u64 *l4 = NULL, *l3, *l2, *l1;
-    u32 l4_index = 0, l3_index, l2_index, l1_index;
+    struct dma_pte pte;
+    u64 *l;
+    u32 l_index;
     u32 i = 0;
     int level = agaw_to_level(hd->agaw);
 
@@ -176,20 +177,17 @@ void print_vtd_entries(struct domain *d, int bus, int devfn,
 
         iommu = drhd->iommu;
         root_entry = iommu->root_entry;
-        printk("    root_entry = %p\n", root_entry);
         if ( root_entry == NULL )
         {
             printk("    root_entry == NULL\n");
             continue;
         }
 
+        printk("    root_entry = %p\n", root_entry);
         printk("    root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
-        printk("    maddr_to_virt(root_entry[%x]) = %p\n",
-               bus, maddr_to_virt(root_entry[bus].val));
-
-        if ( root_entry[bus].val == 0 )
+        if ( !root_present(root_entry[bus]) )
         {
-            printk("    root_entry[%x].lo == 0\n", bus);
+            printk("    root_entry[%x] not present\n", bus);
             continue;
         }
 
@@ -201,73 +199,44 @@ void print_vtd_entries(struct domain *d, int bus, int devfn,
             continue;
         }
 
-        if ( ctxt_entry[devfn].lo == 0 )
-        {
-            printk("    ctxt_entry[%x].lo == 0\n", devfn);
-            continue;
-        }
-
         printk("    context = %p\n", ctxt_entry);
         printk("    context[%x] = %"PRIx64" %"PRIx64"\n",
                devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
-        printk("    maddr_to_virt(context[%x].lo) = %p\n",
-               devfn, maddr_to_virt(ctxt_entry[devfn].lo));
-        printk("    context[%x] = %"PRIx64"\n", devfn, ctxt_entry[devfn].lo);
-
-        switch ( level )
+        if ( !context_present(ctxt_entry[devfn]) )
         {
-        case VTD_PAGE_TABLE_LEVEL_3:
-            l3 = maddr_to_virt(ctxt_entry[devfn].lo);
-            l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
-            printk("    l3 = %p\n", l3);
-            if ( l3 == NULL )
-                continue;
-            l3_index = get_level_index(gmfn, 3);
-            printk("    l3_index = %x\n", l3_index);
-            printk("    l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
-
-            break;
-        case VTD_PAGE_TABLE_LEVEL_4:
-            l4 = maddr_to_virt(ctxt_entry[devfn].lo);
-            l4 = (u64*)(((unsigned long)l4 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
-            printk("    l4 = %p\n", l4);
-            if ( l4 == NULL )
-                continue;
-            l4_index = get_level_index(gmfn, 4);
-            printk("    l4_index = %x\n", l4_index);
-            printk("    l4[%x] = %"PRIx64"\n", l4_index, l4[l4_index]);
-
-            l3 = maddr_to_virt(l4[l4_index]);
-            l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
-            printk("    l3 = %p\n", l3);
-            if ( l3 == NULL )
-                continue;
-            l3_index = get_level_index(gmfn, 3);
-            printk("    l3_index = %x\n", l3_index);
-            printk("    l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
-
-            break;
-        default:
-            printk("Unsupported VTD page table level (%d)!\n", level);
+            printk("    ctxt_entry[%x] not present\n", devfn);
             continue;
         }
 
-        l2 = maddr_to_virt(l3[l3_index]);
-        l2 = (u64*)(((unsigned long)l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
-        printk("    l2 = %p\n", l2);
-        if ( l2 == NULL )
+        if ( level != VTD_PAGE_TABLE_LEVEL_3 &&
+             level != VTD_PAGE_TABLE_LEVEL_4)
+        {
+            printk("Unsupported VTD page table level (%d)!\n", level);
             continue;
-        l2_index = get_level_index(gmfn, 2);
-        printk("    l2_index = %x\n", l2_index);
-        printk("    l2[%x] = %"PRIx64"\n", l2_index, l2[l2_index]);
+        }
 
-        l1 = maddr_to_virt(l2[l2_index]);
-        l1 = (u64*)(((unsigned long)l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
-        printk("    l1 = %p\n", l1);
-        if ( l1 == NULL )
-            continue;
-        l1_index = get_level_index(gmfn, 1);
-        printk("    l1_index = %x\n", l1_index);
-        printk("    l1[%x] = %"PRIx64"\n", l1_index, l1[l1_index]);
-   }
+        l = maddr_to_virt(ctxt_entry[devfn].lo);
+        do
+        {
+            l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
+            printk("    l%d = %p\n", level, l);
+            if ( l == NULL )
+            {
+                printk("    l%d == NULL\n", level);
+                break;
+            }
+            l_index = get_level_index(gmfn, level);
+            printk("    l%d_index = %x\n", level, l_index);
+            printk("    l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]);
+
+            pte.val = l[l_index];
+            if ( !dma_pte_present(pte) )
+            {
+                printk("    l%d[%x] not present\n", level, l_index);
+                break;
+            }
+
+            l = maddr_to_virt(l[l_index]);
+        } while ( --level );
+    }
 }